package com.yu1996.stack;

public class Calculator {

    public static void main(String[] args) {
        //定义运算的表达式
        String s = "50-3+3+2*6-2-3-2";
        //分别定义两个栈存放数字 和 运算符
        CalculatorStack stack1 = new CalculatorStack(10);
        CalculatorStack stack2 = new CalculatorStack(10);
        int index = 0;
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char car = ' ';
        String numKey = "";
        while (true) {
            //循环遍历每个字符
            car = s.substring(index, index + 1).charAt(0);
            //判断字符是数字还是运算符
            if (stack2.isSymbol(car)) {
                //判断运算符栈中是否为空
                if (stack2.isEmpty()) {
                    //如果是空栈  直接入栈
                    stack2.push(car);
                } else {
                    //非空  判断运算符优先级
                    if (stack2.priority(stack2.getTopVal()) < stack2.priority(car)) {
                        //优先级小于等于栈顶运算符时   入栈
                        stack2.push(car);
                    } else {
                        //优先级小于栈顶运算符  则从数栈中取出两个数运算  将结果再压入数栈
                        num1 = stack1.pop();
                        num2 = stack1.pop();
                        oper = stack2.pop();
                        res = stack1.cal(num1, num2, oper);
                        stack1.push(res);
                        stack2.push(car);
                    }
                }
            } else {

//                将字符先拼串
                numKey += car;
                //判断是否是最后一个字符（如果不判断后面会报数组越界错误）
                if (index == s.length() - 1) {
                    stack1.push(car - 48);
                } else {
                    //判断是否是一位数
                    if (stack2.isSymbol(s.substring(index + 1, index + 2).charAt(0))) {
                        //如果下一个是运算符则 将串转化成数存入数栈
                        stack1.push(Integer.parseInt(numKey));
                        //将字符串初始化
                        numKey = "";
                    }
                }
                //如果为数字  直接加入数栈
//                stack1.push(car - 48);
            }
            index++;
            if (index >= s.length()) {
                break;
            }
        }
        //所有表达式都已入栈   最后再将栈中剩余的运算符运算结束
        while (true) {
            if (stack2.isEmpty()) {
                break;
            }
            num1 = stack1.pop();
            num2 = stack1.pop();
            oper = stack2.pop();
            res = stack1.cal(num1, num2, oper);
            stack1.push(res);
        }
        //输出最后结果
        System.out.printf("表达式%s=%d", s, stack1.getTopVal());

    }
}


//定义栈
class CalculatorStack {
    private int maxSize;
    private int[] arr;
    private int top = -1;

    public CalculatorStack(int maxSize) {
        this.maxSize = maxSize;
        //初始化数组
        arr = new int[maxSize];
    }


    /**
     * @Description 判断优先级  （按照数字递增）
     * @Author xing
     * @Date 2019/8/7 11:18
     * @Param
     * @Return
     * @Exception
     */
    public int priority(int oper) {
        if (oper == '*' || oper == '/') {
            return 1;
        } else if (oper == '+' || oper == '-') {
            return 0;
        } else {
            return -1;
        }
    }


    /**
     * @Description 判断遍历的是否是字符（只有两种  除了运算符就是数字）
     * @Author xing
     * @Date 2019/8/7 11:21
     * @Param
     * @Return
     * @Exception
     */
    public boolean isSymbol(int temp) {
        return temp == '+' || temp == '-' || temp == '*' || temp == '/';
    }


    /**
     * @Description 计算方法   num1：栈顶的数   num2：次栈顶数   oper：运算符号
     * @Author xing
     * @Date 2019/8/7 12:50
     * @Param
     * @Return
     * @Exception
     */
    public int cal(int num1, int num2, int oper) {
        //用于存放计算的结果
        int res = 0;
        switch (oper) {
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                System.out.println("输入不合法");
                break;
        }
        return res;
    }


    /**
     * @Description 获得栈顶元素的值  不出栈
     * @Author xing
     * @Date 2019/8/7 12:56
     * @Param
     * @Return
     * @Exception
     */
    public int getTopVal() {
        return arr[top];
    }

    /**
     * @Description 判断栈是否已满
     * @Author xing
     * @Date 2019/8/4 11:29
     * @Param
     * @Return
     * @Exception
     */
    public boolean isFull() {
        return top == maxSize - 1;
    }


    /**
     * @Description 判断栈是否为空
     * @Author xing
     * @Date 2019/8/4 11:29
     * @Param
     * @Return
     * @Exception
     */
    public boolean isEmpty() {
        return top == -1;
    }


    /**
     * @Description 入栈
     * @Author xing
     * @Date 2019/8/4 11:30
     * @Param
     * @Return
     * @Exception
     */
    public void push(int val) {
        //判断是否栈满
        if (isFull()) {
            System.out.println("栈满，无法入栈");
            return;
        }
        top++;
        arr[top] = val;
    }


    /**
     * @Description 出栈
     * @Author xing
     * @Date 2019/8/4 11:32
     * @Param
     * @Return
     * @Exception
     */
    public int pop() {
        //判断是否栈空
        if (isEmpty()) {
            throw new RuntimeException("栈空，无法出栈");
        }
        int val = arr[top];
        top--;
        return val;
    }

    public void list() {
        //判断是否为空
        if (isEmpty()) {
            System.out.println("栈空，无法输出");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("arr[%d]=%d\n", i, arr[i]);
        }
    }
}